#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <cstring>
#include <curl/curl.h>
#include <functional>
#include <memory>
#include "Common.hpp"
#include "log.hpp"


enum 
{
    FileOpen_Err,
};

// 剥离出所有的url文章链接
class StripOutUrl
{
    void Extract_Url(const std::string &line)
    {
        // 1. 从字符串中查找 href=" 字段的位置
        // 2. 从 href=" 后面开始截取字符串获取url信息
        
        static std::string prev_url = "href=\"";
        static std::string back_url = "\"";
        static std::string correct_url_prev = "https://blog.csdn.net/2401_87944878/article";

        size_t len = correct_url_prev.size();
        size_t start = 0;
        while(1)
        {
            size_t pos = line.find(prev_url , start);
            if(pos == std::string::npos) 
                break;
            size_t left_pos = pos + prev_url.size();             // url的起始位置
            size_t right_pos = line.find(back_url , left_pos);   // url结束的位置
            if(right_pos == std::string::npos) 
                break;

            std::string url = line.substr(left_pos , right_pos - left_pos);
            // 将截取的字符串与文章字符串进行比较
            if(strncmp(correct_url_prev.c_str() , url.c_str() , len) == 0){
                _all_url.push_back(std::move(url));
            }
            start = right_pos + 1;
        }
    }
public:
    StripOutUrl(const std::string filepath)
    :_rawfile_path(filepath)
    {}

    void Start()
    {
        // 1. 打开文件
        // 2. 提取文件内容
        // 3. 提取字符串中的url

        std::ifstream ifs(_rawfile_path);
        if(!ifs.is_open()){
            // 没有找到对应的文件;
            // 此时选择使用日志进行错误信息输出，关于日志之前文章中详细介绍过如何进制作
            Log_ns::Log(Log_ns::Fatal) << "File not found";
            exit(FileOpen_Err);
        } 

        std::vector<std::string> all_lines;
        while(1){
            std::string line;
            if(!getline(ifs , line)) 
                break;
            all_lines.push_back(std::move(line));
        }
        for(auto &str : all_lines){
            // 对字符串中的链接进行查找
            Extract_Url(str);
        }
    }

    std::vector<std::string>& Get_url()
    {
        return _all_url;
    }
private:
    std::string _rawfile_path;            // 存储原生的html文件路径
    std::vector<std::string> _all_url;    // 存储所有博主的文章链接  
};

size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
    int real_num = size * nmemb;
    char *str = static_cast<char *>(buffer);
    std::shared_ptr<html_base> html_ptr = *(static_cast<std::shared_ptr<html_base> *>(userp));
    html_ptr->_content += str;

    return real_num;
}

class Get_HTML_files
{
public:
    Get_HTML_files()
    {
        curl_global_init(CURL_GLOBAL_DEFAULT);
        curl = curl_easy_init();
    }

    void Init()
    {
        // 1. 对curl句柄进行设置: 引入证书, 去掉返回结果的请求报头,设置回调函数
        curl_easy_setopt(curl , CURLOPT_CAINFO , "/home/banju/boost_search_web/blog_article/cacert.pem");  // 引入证书
        curl_easy_setopt(curl , CURLOPT_HEADER , 0);
        curl_easy_setopt(curl , CURLOPT_WRITEFUNCTION , write_data);
    }

    std::shared_ptr<html_base> Get_Html(const std::string &url)
    {
        // 1. 提取文件名称
        // 2. 获取html文件信息: 设置访问地址 , 设置参数
        // 3. 将html的数据返回

        std::shared_ptr<html_base> hb_ptr(new html_base);

        hb_ptr->_url = url;
        
        curl_easy_setopt(curl , CURLOPT_URL , url.c_str());
        curl_easy_setopt(curl , CURLOPT_WRITEDATA , &hb_ptr);
        CURLcode code = curl_easy_perform(curl);
        if(code != CURLE_OK)
        {
            std::cout << curl_easy_strerror(code) << std::endl;
        }
        return hb_ptr;
    }

    ~Get_HTML_files()
    {
        curl_easy_cleanup(curl);
        curl_global_cleanup();
    }

private:
    std::string _dir_path;
    CURL* curl;     
};